package com.report.service;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.JSONPath;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.data.*;
import com.report.bizUtil.TableHeaderUtil;
import com.report.bo.TableHeaderResultBo;
import com.report.entity.Report;
import com.report.entity.ReportExportTemplate;
import com.report.entity.ReportTemplate;
import com.report.entity.TablePlaceholder;
import com.report.repository.ReportExportTemplateRepository;
import com.report.repository.ReportRepository;
import com.report.repository.ReportTemplateRepository;
import com.report.repository.TablePlaceholderRepository;
import com.report.vo.ExportReportReq;
import com.report.vo.TablePlaceholderVo;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@Service
public class ReportExportService {

    @Resource
    private ReportExportTemplateRepository reportExportTemplateRepository;
    @Resource
    private TablePlaceholderRepository tablePlaceholderRepository;
    @Resource
    private ReportRepository reportRepository;
    @Resource
    private ReportTemplateRepository reportTemplateRepository;


    public void addReportExportTemplate(ReportExportTemplate reportExportTemplate) {
        String url = reportExportTemplate.getUrl();
        reportExportTemplate.setFileName(url.substring(url.lastIndexOf("_@") + 2));
        reportExportTemplateRepository.save(reportExportTemplate);
    }

    public List<ReportExportTemplate> findReportExportTemplate(ReportExportTemplate reportExportTemplate) {
        return reportExportTemplateRepository.getReportExportTemplateByCreatedBy(reportExportTemplate.getCreatedBy());
    }

    public void addPlaceholder(TablePlaceholder placeholder) {
        tablePlaceholderRepository.save(placeholder);
    }

    public List<TablePlaceholderVo> getPlaceholders() {
        List<TablePlaceholder> allNodes = tablePlaceholderRepository.findAll();
        List<TablePlaceholderVo> list = Convert.toList(TablePlaceholderVo.class, allNodes);

        // 1. 按rowId构建映射，便于快速查找节点
        Map<String, TablePlaceholderVo> nodeMap = list.stream()
                .collect(Collectors.toMap(TablePlaceholderVo::getRowId, node -> node));

        // 2. 按pId分组，建立父子关系映射
        Map<String, List<TablePlaceholderVo>> childrenMap = list.stream()
                .filter(node -> node.getPId() != null && !node.getPId().isEmpty())
                .collect(Collectors.groupingBy(TablePlaceholderVo::getPId));

        // 3. 为每个节点设置子节点
        list.forEach(node -> {
            String rowId = node.getRowId();
            List<TablePlaceholderVo> children = childrenMap.get(rowId);
            node.setChildren(children != null ? children : new ArrayList<>());
        });

        // 4. 返回根节点（pId为null或空，或者pId不在nodeMap中的节点）
        return list.stream()
                .filter(node ->
                        node.getPId() == null ||
                                node.getPId().isEmpty() ||
                                !nodeMap.containsKey(node.getPId()))
                .collect(Collectors.toList());
    }

    public byte[] exportReport(ExportReportReq exportReportReq, StringBuilder fileName) {
        Optional<ReportExportTemplate> exportTemplate = reportExportTemplateRepository.findById(exportReportReq.getTableTemplateId());
        if (!exportTemplate.isPresent()) {
            throw new RuntimeException("未找到导出模板");
        }
        // 读取文件到字节数组
        byte[] fileBytes = HttpUtil.downloadBytes(exportTemplate.get().getUrl());
        //回写文件名
        String url = exportTemplate.get().getUrl();
        fileName.append(url.substring(url.lastIndexOf("_@") + 2));

        //表中所有占位数据
        Map<String, Object> placeholders = new HashMap<>();

        try {
            //获取所有占位符
            List<TablePlaceholder> tablePlaceholders = tablePlaceholderRepository.findAllById(exportReportReq.getIds());
            for (TablePlaceholder tablePlaceholder : tablePlaceholders) {
                System.out.println(tablePlaceholder.getId());
                Report report = reportRepository.getReport(tablePlaceholder.getTableName(), exportReportReq.getCurrentCompanyUscc(), exportReportReq.getMergeType());
                String reportInfo = "";
                if (report != null) {
                    reportInfo = report.getReportinfo();
                } else {
                    //查模板表
                    ReportTemplate reportTemplateByReporttype = reportTemplateRepository.getReportTemplateByReporttype(tablePlaceholder.getTableName());
                    if (reportTemplateByReporttype == null) {
                        continue;
                    }
                    reportInfo = reportTemplateByReporttype.getReportinfo();
                }
                if (StringUtils.isBlank(reportInfo)) {
                    continue;
                }
                //RowRenderData[] rowRenderData = buildPlaceholderData(reportInfo);
                TableRenderData tableRenderData = buildPlaceholderData(reportInfo);
                placeholders.put(tablePlaceholder.getPlaceholder(), tableRenderData);
            }
            if (CollectionUtil.isEmpty(placeholders)) {
                throw new RuntimeException("未查到当前树形节点的模板数据");
            }

            //处理占位数据
            return deleteTemplate(fileBytes, placeholders);

        } catch (IOException e) {
            e.printStackTrace();
        }
        throw new RuntimeException("导出异常");
    }

    /**
     * 组装占位符数据
     *
     * @param reportInfo
     * @return
     */
    public TableRenderData buildPlaceholderData(String reportInfo) {
        //header处理
        List<JSONObject> headers = JSONPath.read(reportInfo, "$.header", List.class);
        //清除主键列
        headers.remove(0);
        //清除行标列
        headers.remove(headers.size() - 1);

        TableHeaderResultBo tableHeaderResultBo = TableHeaderUtil.processHeader(JSON.toJSONString(headers));
        MergeCellRule.MergeCellRuleBuilder ruleBuilder = MergeCellRule.builder();
        tableHeaderResultBo.processMergeRules(ruleBuilder);

        MergeCellRule rules = ruleBuilder.build();

        //data处理
        List<JSONArray> datas = JSONPath.read(reportInfo, "$.data", List.class);
        RowRenderData[] rowRenderData = new RowRenderData[datas.size() - 1 + tableHeaderResultBo.getRows().size()];
        for (int i = 0; i < tableHeaderResultBo.getRows().size(); i++) {
            List<String> row = tableHeaderResultBo.getRows().get(i);
            rowRenderData[i] = Rows.create(row.toArray(new String[row.size()]));
        }
        //数据行起始下标
        int i = tableHeaderResultBo.getRows().size();
        datas.remove(0);
        for (JSONArray data : datas) {
            List<String> row = JSON.parseArray(data.toJSONString(), String.class).stream().map(s -> s == null ? "" : s).collect(Collectors.toList());
            //清除主键列
            row.remove(0);
            //清除行唯一标识列
            row.remove(row.size() - 1);
            rowRenderData[i] = Rows.create(row.toArray(new String[row.size()]));
            i++;
        }


        return Tables.of(rowRenderData).mergeRule(rules).create();
    }


    public static byte[] deleteTemplate(byte[] inputStream, Map<String, Object> maps) throws IOException {
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(1024);

        XWPFTemplate template = XWPFTemplate.compile(new ByteArrayInputStream(inputStream));
        template.render(maps);
        template.writeAndClose(byteArrayOutputStream);
        //template.writeAndClose(new FileOutputStream("G:\\output.docx"));

        /*RowRenderData row0 = Rows.of("姓名", "学历")
                .verticalCenter()
                .textColor("FFFFFF")
                .bgColor("4472C4")
                .center()
                .create();*/


        return byteArrayOutputStream.toByteArray();
    }


    /**
     * 获取文档内所有占位符
     *
     * @param document 文档对象
     * @param regex    占位符正则表达式
     * @return
     */
    public static List<String> getPlaceholderName(XWPFDocument document, String regex) {
        List<String> matchedTextList = new ArrayList<>();
        for (XWPFParagraph paragraph : document.getParagraphs()) {
            String text = paragraph.getText();
            Pattern pattern = Pattern.compile(regex);
            Matcher matcher = pattern.matcher(text);
            while (matcher.find()) {
                matchedTextList.add(matcher.group());
            }
        }
        return matchedTextList;
    }

}
